// Copyright (C) 2022 Beken Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <driver/int.h>
#include <os/mem.h>
#include <driver/gpio.h>
#include <driver/gpio_types.h>
#include <driver/jpeg_enc.h>
#include <driver/jpeg_enc_types.h>
#include <driver/dvp_camera.h>
#include <driver/dvp_camera_types.h>

#include <driver/i2c.h>

#define OV2640_WRITE_ADDRESS (0x60)
#define OV2640_READ_ADDRESS (0x61)

#define TAG "ov2640"
#define LOGI(...) BK_LOGI(TAG, ##__VA_ARGS__)

#define OV2640_CHIP_PIDH (0x26)
#define OV2640_CHIP_PIDL (0x42)

#define SENSOR_I2C_RERAD(reg, value)  cb->read_uint8((OV2640_WRITE_ADDRESS >> 1), reg, value)
#define SENSOR_I2C_WRITE(reg, value)  cb->write_uint8((OV2640_WRITE_ADDRESS >> 1), reg, value)


#if 0
const uint8_t sensor_ov2640_init_talbe[][2] =
{
	{0xff, 0x00},
	{0x2c, 0xff},
	{0x2e, 0xdf},
	{0xff, 0x01},
	{0x3c, 0x32},
	/*!<*/
	{0x11, 0x00},
	{0x09, 0x02},
	{0x04, 0xD8},/*!< Mirror horizontally, flip vertically */
	{0x13, 0xe5},
	{0x14, 0x48},
	{0x2c, 0x0c},
	{0x33, 0x78},
	{0x3a, 0x33},
	{0x3b, 0xfB},
	/*!<*/
	{0x3e, 0x00},
	{0x43, 0x11},
	{0x16, 0x10},
	/*!<*/
	{0x39, 0x92},
	/*!<*/
	{0x35, 0xda},
	{0x22, 0x1a},
	{0x37, 0xc3},
	{0x23, 0x00},
	{0x34, 0xc0},
	{0x36, 0x1a},
	{0x06, 0x88},
	{0x07, 0xc0},
	{0x0d, 0x87},
	{0x0e, 0x41},
	{0x4c, 0x00},

	{0x48, 0x00},
	{0x5B, 0x00},
	{0x42, 0x03},
	/*!<*/
	{0x4a, 0x81},
	{0x21, 0x99},
	/*!<*/
	{0x24, 0x40},
	{0x25, 0x38},
	{0x26, 0x82},
	{0x5c, 0x00},
	{0x63, 0x00},
	{0x46, 0x00},
	{0x0c, 0x3c},
	/*!<*/
	{0x61, 0x70},
	{0x62, 0x80},
	{0x7c, 0x05},
	/*!<*/
	{0x20, 0x80},
	{0x28, 0x30},
	{0x6c, 0x00},
	{0x6d, 0x80},
	{0x6e, 0x00},
	{0x70, 0x02},
	{0x71, 0x94},
	{0x73, 0xc1},
	{0x3d, 0x34},
	{0x5a, 0x57},

	{0x12, 0x00},//UXGA 1600*1200
	{0x17, 0x11},
	{0x18, 0x75},
	{0x19, 0x01},
	{0x1a, 0x97},
	{0x32, 0x36},
	{0x03, 0x0f},
	{0x37, 0x40},

	{0x4f, 0xca},
	{0x50, 0xa8},
	{0x5a, 0x23},
	{0x6d, 0x00},
	{0x6d, 0x38},
	/*!<*/
	{0xff, 0x00},
	{0xe5, 0x7f},
	{0xf9, 0xc0},
	{0x41, 0x24},
	{0xe0, 0x14},
	{0x76, 0xff},
	{0x33, 0xa0},
	{0x42, 0x20},
	{0x43, 0x18},
	{0x4c, 0x00},
	{0x87, 0xd5},
	{0x88, 0x3f},
	{0xd7, 0x03},
	{0xd9, 0x10},
	{0xd3, 0x82},
	/*!<*/
	{0xc8, 0x08},
	{0xc9, 0x80},
	/*!<*/
	{0x7c, 0x00},
	{0x7d, 0x00},
	{0x7c, 0x03},
	{0x7d, 0x48},
	{0x7d, 0x48},
	{0x7c, 0x08},
	{0x7d, 0x20},
	{0x7d, 0x10},
	{0x7d, 0x0e},
	/*!<*/
	{0x90, 0x00},
	{0x91, 0x0e},
	{0x91, 0x1a},
	{0x91, 0x31},
	{0x91, 0x5a},
	{0x91, 0x69},
	{0x91, 0x75},
	{0x91, 0x7e},
	{0x91, 0x88},
	{0x91, 0x8f},
	{0x91, 0x96},
	{0x91, 0xa3},
	{0x91, 0xaf},
	{0x91, 0xc4},
	{0x91, 0xd7},
	{0x91, 0xe8},
	{0x91, 0x20},
	/*!<*/
	{0x92, 0x00},
	{0x93, 0x06},
	{0x93, 0xe3},
	{0x93, 0x05},
	{0x93, 0x05},
	{0x93, 0x00},
	{0x93, 0x04},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	/*!<*/
	{0x96, 0x00},
	{0x97, 0x08},
	{0x97, 0x19},
	{0x97, 0x02},
	{0x97, 0x0c},
	{0x97, 0x24},
	{0x97, 0x30},
	{0x97, 0x28},
	{0x97, 0x26},
	{0x97, 0x02},
	{0x97, 0x98},
	{0x97, 0x80},
	{0x97, 0x00},
	{0x97, 0x00},
	/*!<*/
	{0xc3, 0xef},

	{0xa4, 0x00},
	{0xa8, 0x00},
	{0xc5, 0x11},
	{0xc6, 0x51},
	{0xbf, 0x80},
	{0xc7, 0x10},
	{0xb6, 0x66},
	{0xb8, 0xA5},
	{0xb7, 0x64},
	{0xb9, 0x7C},
	{0xb3, 0xaf},
	{0xb4, 0x97},
	{0xb5, 0xFF},
	{0xb0, 0xC5},
	{0xb1, 0x94},
	{0xb2, 0x0f},
	{0xc4, 0x5c},
	/*!<*/
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x8c, 0x00},
	{0x86, 0x3d},
	{0x50, 0x00},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},

	{0x5a, 0x90},
	{0x5b, 0x2C},
	{0x5c, 0x05},

	{0xd3, 0x82},
	{0xc3, 0xed},
	{0x7f, 0x00},
	{0xda, 0x00},
	{0xe5, 0x1f},
	{0xe1, 0x67},
	{0xe0, 0x00},
	{0xdd, 0x7f},
	{0xc2, 0x08 | 0x04},
	{0x05, 0x00},
};
#endif

#if 0  //800X600
const uint8_t sensor_ov2640_init_talbe[][2] =
{
	{0xff, 0x00},
	{0x2c, 0xff},
	{0x2e, 0xdf},
	{0xff, 0x01},
	{0x3c, 0x32},
	{0x11, 0x80}, //chen 0x01
	{0x09, 0x02},
	{0x04, 0xd0},   //水平翻转
	{0x13, 0xe5},
	{0x14, 0x48},
	{0x15,  0x00}, //Invert VSYNC

	{0x2c, 0x0c},
	{0x33, 0x78},
	{0x3a, 0x33},
	{0x3b, 0xfB},

	{0x3e, 0x00},
	{0x43, 0x11},
	{0x16, 0x10},
	{0x39, 0x02},
	{0x35, 0xda},
	{0x22, 0x1a},
	{0x37, 0xc3},
	{0x23, 0x00},
	{0x34, 0xc0},
	{0x36, 0x1a},
	{0x06, 0x88},
	{0x07, 0xc0},
	{0x0d, 0x87},
	{0x0e, 0x41},
	{0x4c, 0x00},
	{0x4a, 0x81},
	{0x21, 0x99},
	{0x24, 0x40},
	{0x25, 0x38},
	{0x26, 0x82},
	{0x5c, 0x00},
	{0x63, 0x00},
	{0x46, 0x22},
	{0x61, 0x70},
	{0x62, 0x80},
	{0x7c, 0x05},
	{0x20, 0x80},
	{0x28, 0x30},
	{0x6c, 0x00},
	{0x6d, 0x80},
	{0x6e, 0x00},
	{0x70, 0x02},
	{0x71, 0x94},
	{0x73, 0xc1},
	{0x3d, 0x34},
	{0x5a, 0x23},
	{0x4f, 0xbb},
	{0x50, 0x9c},
	{0x12, 0x40},
	{0x17, 0x11},
	{0x18, 0x43},
	{0x19, 0x00},
	{0x1a, 0x4b},
	{0x32, 0x09},
	{0x37, 0xc0},
	{0x4f, 0xca},
	{0x50, 0xa8},
	{0x6d, 0x00},
	{0x3d, 0x38},
	{0xff, 0x00},
	{0xe5, 0x7f},
	{0xf9, 0xc0},
	{0x41, 0x24},
	{0xe0, 0x14},
	{0x76, 0xff},
	{0x33, 0xa0},
	{0x42, 0x20},
	{0x43, 0x18},
	{0x4c, 0x00},
	{0x87, 0xd0},
	{0x88, 0x3f},
	{0xd7, 0x03},
	{0xd9, 0x10},
	{0xd3, 0x82},
	{0xc8, 0x08},
	{0xc9, 0x80},
	{0x7c, 0x00},
	{0x7d, 0x00},
	{0x7c, 0x03},
	{0x7d, 0x48},
	{0x7d, 0x48},
	{0x7c, 0x08},
	{0x7d, 0x20},
	{0x7d, 0x10},
	{0x7d, 0x0e},
	{0x90, 0x00},
	{0x91, 0x0e},
	{0x91, 0x1a},
	{0x91, 0x31},
	{0x91, 0x5a},
	{0x91, 0x69},
	{0x91, 0x75},
	{0x91, 0x7e},
	{0x91, 0x88},
	{0x91, 0x8f},
	{0x91, 0x96},
	{0x91, 0xa3},
	{0x91, 0xaf},
	{0x91, 0xc4},
	{0x91, 0xd7},
	{0x91, 0xe8},
	{0x91, 0x20},
	{0x92, 0x00},
	{0x93, 0x06},
	{0x93, 0xe3},
	{0x93, 0x05},
	{0x93, 0x05},
	{0x93, 0x00},
	{0x93, 0x04},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x96, 0x00},
	{0x97, 0x08},
	{0x97, 0x19},
	{0x97, 0x02},
	{0x97, 0x0c},
	{0x97, 0x24},
	{0x97, 0x30},
	{0x97, 0x28},
	{0x97, 0x26},
	{0x97, 0x02},
	{0x97, 0x98},
	{0x97, 0x80},
	{0x97, 0x00},
	{0x97, 0x00},
	{0xc3, 0xed},
	{0xa4, 0x00},
	{0xa8, 0x00},
	{0xc5, 0x11},
	{0xc6, 0x51},
	{0xbf, 0x80},
	{0xc7, 0x10},
	{0xb6, 0x66},
	{0xb8, 0xA5},
	{0xb7, 0x64},
	{0xb9, 0x7C},
	{0xb3, 0xaf},
	{0xb4, 0x97},
	{0xb5, 0xFF},
	{0xb0, 0xC5},
	{0xb1, 0x94},
	{0xb2, 0x0f},
	{0xc4, 0x5c},
	{0xc0, 0x64},
	{0xc1, 0x4B},
	{0x8c, 0x00},
	{0x86, 0x3D},
	{0x50, 0x00},
	{0x51, 0xC8},
	{0x52, 0x96},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x00},
	{0x5a, 0xC8},
	{0x5b, 0x96},
	{0x5c, 0x00},
	{0xd3, 0x82},
	{0xc3, 0xed},
	{0x7f, 0x00},
	{0xda, 0x00},
	{0xe5, 0x1f},
	{0xe1, 0x67},
	{0xe0, 0x00},
	{0xdd, 0x7f},
	{0x05, 0x00},
};
#endif


const uint8_t sensor_ov2640_init_talbe[][2] =
{
	{0xff, 0x01},
	{0x12, 0x80},
	{0xff, 0x00},
	{0x2c, 0xff},
	{0x2e, 0xdf},
	{0xff, 0x01},

	{0x03, 0x0f}, // 0x8f peak    //4f    //Bit[7:6]: Dummy frame control
	{0x0f, 0x4b},


	{0x3c, 0x32},
	{0x11, 0x00},
	{0x09, 0x01}, //03},  //Bit[1:0]: Output drive select
	{0x04, 0xa8}, //b7,b6 directs
	{0x13, 0xe5},
	{0x14, 0x28}, //0x48 peak
	{0x2c, 0x0c},
	{0x33, 0x78},
	{0x3a, 0x33},
	{0x3b, 0xfB},
	{0x3e, 0x00},
	{0x43, 0x11},
	{0x16, 0x10},
	{0x39, 0x02},
	{0x35, 0x88},
	{0x22, 0x09},
	{0x37, 0x40},
	{0x23, 0x00},
	{0x34, 0xa0},
	{0x36, 0x1a},
	{0x06, 0x02},
	{0x07, 0xc0},
	{0x0d, 0xb7},
	{0x0e, 0x01},
	{0x4c, 0x00},
	{0x4a, 0x81},
	{0x21, 0x99},
	//aec
	//{{0x24},{0x58}},
	//{{0x25},{0x50}},
	//{{0x26},{0x92}},

	//{{0x24, 0x70}},
	//{{0x25, 0x60}},
	//{{0x26, 0xa4}},
	{0x24, 0x48},
	{0x25, 0x38}, //40
	{0x26, 0x82}, //82

	{0x5c, 0x00},
	{0x63, 0x00},
	{0x46, 0x3f},
	{0x0c, 0x3c},
	{0x61, 0x70},
	{0x62, 0x80},
	{0x7c, 0x05},
	{0x20, 0x80},
	{0x28, 0x30},
	{0x6c, 0x00},
	{0x6d, 0x80},
	{0x6e, 0x00},
	{0x70, 0x02},
	{0x71, 0x94},
	{0x73, 0xc1},
	{0x3d, 0x34},
	{0x5a, 0x57},
	{0x4f, 0xbb},
	{0x50, 0x9c},
	{0xff, 0x00},
	{0xe5, 0x7f},
	{0xf9, 0xc0},
	{0x41, 0x24},
	{0xe0, 0x14},
	{0x76, 0xff},
	{0x33, 0xa0},
	{0x42, 0x20},
	{0x43, 0x18},
	{0x4c, 0x00},
	{0x87, 0xd0},
	{0x88, 0x3f},
	{0xd7, 0x03},
	{0xd9, 0x10},
	{0xd3, 0x82},
	{0xc8, 0x08},
	{0xc9, 0x80},
	//
	//{{0xff},{0x00}}, //added by peak on 20120409
	{0x7c, 0x00},
	{0x7d, 0x02}, //0x00 peak//0x07
	{0x7c, 0x03},
	{0x7d, 0x28}, //0x48//0x40
	{0x7d, 0x28}, //0x48 peak//0x40

	// removed by peak on 20120409

	{0x7c, 0x08},
	{0x7d, 0x20},
	{0x7d, 0x10}, //0x10
	{0x7d, 0x0e}, //0x0e

	//contrast added by peak on 20120409
	{0x7c, 0x00},
	{0x7d, 0x04}, //0x48//0x40
	{0x7c, 0x07}, //0x48 peak//0x40
	{0x7d, 0x20},
	{0x7d, 0x1c},
	{0x7d, 0x2a}, //0x10
	{0x7d, 0x06}, //0x0e

	{0xff, 0x00}, //register page
	{0x7c, 0x00},
	{0x7d, 0x04},
	{0x7c, 0x09},
	{0x7d, 0x00}, //brightness value
	{0x7d, 0x00}, //sign

	{0xff, 0x00},
	{0x7c, 0x00},
	{0x7d, 0x00},
	{0x7c, 0x05},
	{0x7d, 0x80},
	{0x7d, 0x80},

	{0x90, 0x00},
	{0x91, 0x0e},
	{0x91, 0x1a}, //e3
	{0x91, 0x31},
	{0x91, 0x5a},
	{0x91, 0x69},
	{0x91, 0x75},
	{0x91, 0x7e},
	{0x91, 0x88},
	{0x91, 0x8f},
	{0x91, 0x96},
	{0x91, 0xa3},
	{0x91, 0xaf},
	{0x91, 0xc4},
	{0x91, 0xd7},
	{0x91, 0xe8},
	{0x91, 0x20},

	{0x90, 0x00},
	{0x91, 0x04},
	{0x91, 0x0c},
	{0x91, 0x20},
	{0x91, 0x4c},
	{0x91, 0x60},
	{0x91, 0x74},
	{0x91, 0x82},
	{0x91, 0x8e},
	{0x91, 0x97},
	{0x91, 0x9f},
	{0x91, 0xaa},
	{0x91, 0xb4},
	{0x91, 0xc8},
	{0x91, 0xd9},
	{0x91, 0xe8},
	{0x91, 0x20},



	{0x92, 0x00},
	{0x93, 0x06},
	{0x93, 0xc8}, //e3
	{0x93, 0x05},
	{0x93, 0x05},
	{0x93, 0x00},
	{0x93, 0x04},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},
	{0x93, 0x00},

	{0x96, 0x00},
	{0x97, 0x08},
	{0x97, 0x19},
	{0x97, 0x02},
	{0x97, 0x0c},
	{0x97, 0x24},
	{0x97, 0x30},
	{0x97, 0x28},
	{0x97, 0x26},
	{0x97, 0x02},
	{0x97, 0x98},
	{0x97, 0x80},
	{0x97, 0x00},
	{0x97, 0x00},
	{0xc3, 0xef}, //ed
	{0xa4, 0x00},
	{0xa8, 0x00},

	{0xbf, 0x00},
	{0xba, 0xdc},
	{0xbb, 0x08},
	{0xb6, 0x20},
	{0xb8, 0x30},
	{0xb7, 0x20},
	{0xb9, 0x30},
	{0xb3, 0xb4},
	{0xb4, 0xca},
	{0xb5, 0x34},
	{0xb0, 0x46},
	{0xb1, 0x46},
	{0xb2, 0x06},
	{0xc7, 0x00},
	{0xc6, 0x51},
	{0xc5, 0x11},
	{0xc4, 0x9c},
	///
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x3d},
	{0x50, 0x92},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0x50},
	{0x5b, 0x3c},
	{0x5c, 0x00},
	{0xc3, 0xed},
	{0x7f, 0x00},
	{0xda, 0x01},
	{0xe5, 0x1f},
	{0xe1, 0x67},
	{0xe0, 0x00},
	{0xdd, 0x7f},
	{0x05, 0x00},


#if 1
	{0xff, 0x01},
	{0x5d, 0x55}, //0x00
	//{{0x5e, 0x7d}},//0x3c
	//{{0x5f, 0x7d}},//0x28
	//{{0x60, 0x55}},//0x55
	{0x5e, 0x55}, //0x3c
	{0x5f, 0x55}, //0x28
	{0x60, 0x55}, //0x55

	{0xff, 0x00},
	{0xc3, 0xef},
	{0xa6, 0x00},
	{0xa7, 0x0f},
	{0xa7, 0x4e},
	{0xa7, 0x7a},
	{0xa7, 0x33},
	{0xa7, 0x00},
	{0xa7, 0x23},
	{0xa7, 0x27},
	{0xa7, 0x3a},
	{0xa7, 0x70},
	{0xa7, 0x33},
	{0xa7, 0x00}, //L
	{0xa7, 0x23},
	{0xa7, 0x20},
	{0xa7, 0x0c},
	{0xa7, 0x66},
	{0xa7, 0x33},
	{0xa7, 0x00},
	{0xa7, 0x23},
	{0xc3, 0xef},

	{0xa6, 0x00},
	{0xa7, 0x20},
	{0xa7, 0x00},
	{0xa7, 0x20}, //red   //18
	{0xa7, 0x31},
	{0xa7, 0x10},
	{0xa7, 0x28},
	{0xa7, 0x00},
	{0xa7, 0x20},
	{0xa7, 0x1a}, //green
	{0xa7, 0x31},
	{0xa7, 0x10},
	{0xa7, 0x28},
	{0xa7, 0x00},
	{0xa7, 0x20},
	{0xa7, 0x19}, //blue
	{0xa7, 0x31},
	{0xa7, 0x10},
	{0xa7, 0x28},

#endif


#if 1
	{0xff, 0x00},
	{0x92, 0x00},
	{0x93, 0x06}, //0x06 peak
	{0x93, 0xe3}, //e
	{0x93, 0x05},
	{0x93, 0x03},
	{0x93, 0x00},
	{0x93, 0x04},
#endif

	//{{0x03, 0x0f}},

	{0xe0, 0x04},
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x3d},
	{0x50, 0x89},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0xa0},
	{0x5b, 0x78},
	{0x5c, 0x00},
	{0xd3, 0x82},
	{0xe0, 0x00},

	//YUV422
	{0xff, 0x00},
	{0xda, 0x00},

	{0xff, 0x00},  //AWB auto, bit[1]:0,auto
	{0xc7, 0x00},

	{0xff, 0x00}, //register page
	{0x7c, 0x00},
	{0x7d, 0x00},
	{0x7c, 0x03},
	{0x7d, 0x48},
	{0x7d, 0x48},
	{0x7c, 0x08},
	{0x7d, 0x20},
	{0x7d, 0x10},
	{0x7d, 0x0e},

};


const uint8_t sensor_ov2640_1600X1200_talbe[][2] =
{
	{0xff, 0x00},
	{0xe0, 0x04},
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x3d},
	{0x50, 0x00},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0x90},
	{0x5b, 0x2c},
	{0x5c, 0x05},
	{0xd3, 0x82},
	{0xe0, 0x00},
};

const uint8_t sensor_ov2640_1280X720_talbe[][2] =
{
	{0xff, 0x00},
	{0xe0, 0x04},
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x3d},
	{0x50, 0x00},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0x40},
	{0x5b, 0xb4},
	{0x5c, 0x01},
	{0xd3, 0x82},
	{0xe0, 0x00},
};


const uint8_t sensor_ov2640_1024X768_talbe[][2] =
{
	{0xff, 0x00},
	{0xe0, 0x04},
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x3d},
	{0x50, 0x00},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0x90},
	{0x5b, 0x2c},
	{0x5c, 0x05},
	{0xd3, 0x82},
	{0xe0, 0x00},
};

const uint8_t sensor_ov2640_800X600_talbe[][2] =
{
	{0xff, 0x00},
	{0xe0, 0x04},
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x35},
	{0x50, 0x89},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0xc8},
	{0x5b, 0x96},
	{0x5c, 0x00},
	{0xd3, 0x82},
	{0xe0, 0x00},
};

const uint8_t sensor_ov2640_640X480_talbe[][2] =
{
	{0xe0, 0x04},
	{0xc0, 0xc8},
	{0xc1, 0x96},
	{0x86, 0x3d},
	{0x50, 0x89},
	{0x51, 0x90},
	{0x52, 0x2c},
	{0x53, 0x00},
	{0x54, 0x00},
	{0x55, 0x88},
	{0x57, 0x00},
	{0x5a, 0xa0},
	{0x5b, 0x78},
	{0x5c, 0x00},
	{0xd3, 0x82},
	{0xe0, 0x00},

};


bool ov2640_detect(const dvp_camera_i2c_callback_t *cb)
{
	uint8_t pidh_data = 0, pidhl_data = 0;

	SENSOR_I2C_RERAD(0x0A,  &pidh_data);
	SENSOR_I2C_RERAD(0x0B,  &pidhl_data);

	LOGI("%s, id: 0x%02X%02X\n", __func__, pidh_data, pidhl_data);

	if (pidh_data == OV2640_CHIP_PIDH
	    && pidhl_data == OV2640_CHIP_PIDL)
	{
		LOGI("%s success\n", __func__);
		return true;
	}

	return false;
}


int ov2640_init(const dvp_camera_i2c_callback_t *cb)
{
	uint32_t size = sizeof(sensor_ov2640_init_talbe) / 2, i;

	LOGI("%s\n", __func__);

	for (i = 0; i < size; i++)
	{
		SENSOR_I2C_WRITE(sensor_ov2640_init_talbe[i][0],
		                 sensor_ov2640_init_talbe[i][1]);
	}

	return 0;
}


int ov2640_set_ppi(const dvp_camera_i2c_callback_t *cb, media_ppi_t ppi)
{
	uint32_t size, i;
	int ret = -1;

	LOGI("%s\n", __func__);

	switch (ppi)
	{
		case PPI_1600X1200:
		{
			size = sizeof(sensor_ov2640_1600X1200_talbe) / 2;

			for (i = 0; i < size; i++)
			{
				SENSOR_I2C_WRITE(sensor_ov2640_1600X1200_talbe[i][0],
				                 sensor_ov2640_1600X1200_talbe[i][1]);
			}

			ret = 0;
		}
		break;
		case PPI_1280X720:
		{
			size = sizeof(sensor_ov2640_1280X720_talbe) / 2;

			for (i = 0; i < size; i++)
			{
				SENSOR_I2C_WRITE(sensor_ov2640_1280X720_talbe[i][0],
				                 sensor_ov2640_1280X720_talbe[i][1]);
			}

			ret = 0;
		}
		break;

		case PPI_800X600:
		{
			size = sizeof(sensor_ov2640_800X600_talbe) / 2;

			for (i = 0; i < size; i++)
			{
				SENSOR_I2C_WRITE(sensor_ov2640_800X600_talbe[i][0],
				                 sensor_ov2640_800X600_talbe[i][1]);
			}

			ret = 0;
		}
		break;
		case PPI_640X480:
		{
			size = sizeof(sensor_ov2640_640X480_talbe) / 2;

			for (i = 0; i < size; i++)
			{
				SENSOR_I2C_WRITE(sensor_ov2640_640X480_talbe[i][0],
				                 sensor_ov2640_640X480_talbe[i][1]);
			}

			ret = 0;
		}
		break;

		default:
			break;

	}

	return ret;
}


int ov2640_set_fps(const dvp_camera_i2c_callback_t *cb, sensor_fps_t fps)
{
	int ret = -1;

	LOGI("%s\n", __func__);


	return ret;
}


const dvp_sensor_config_t dvp_sensor_ov2640 =
{
	.name = "ov2640",
	.clk = JPEG_96M_MCLK_16M,
	/* default config */
	.def_ppi = PPI_1280X720,
	.def_fps = FPS15,
	/* capability config */
	.fps_cap = FPS15,
	.ppi_cap = PPI_CAP_1280X720 | PPI_CAP_1600X1200,
	.id = ID_OV2640,
	.address = (OV2640_WRITE_ADDRESS >> 1),
	.init = ov2640_init,
	.detect = ov2640_detect,
	.set_ppi = ov2640_set_ppi,
	.set_fps = ov2640_set_fps,
};

